#pragma once

/*
 * pipe module class.
 */

#include "pipe_config.h"
#include "pipe.h"
#include "all.hpp"
#include "main_service.h"
#include "pipe_session.h"
#include "default_interface.hpp"
#include "pipe_define.h"
#include "time_wheel.h"

namespace anet {
	namespace pipe {
		using sharePtrSession = anet::tcp::CSharePtrSession<CPipeSession>;
		using userSessionFactory = anet::tcp::CSharePtrSessionFactory<CPipeSession>;

		class CPipeModule final : public IPipeModule {
		protected:
			CPipeModule();
			virtual ~CPipeModule();
			CPipeModule(const CPipeModule& rhs) = delete;
			CPipeModule& operator= (const CPipeModule& rhs) = delete;

		public:
			static CPipeModule& instance();
			
		public:
			// init initializes the config and pipe reporter interface
			virtual bool Init(const char* pipePath, IPipeReporter* reporter) override;

			// Run the pipe module for anet net and timer.
			// !!you can ignore it if your project can do it.
			virtual bool Run(int count) override;

			// get local pipe id.
			virtual unsigned int GetLocalId() const override;

			// get reporter.
			virtual IPipeReporter* GetReporter() override;

		public:
			STimeWheelSpace::CTimeWheel& getTimeWheel();

			// get session factory(real return userSessionFactory*).
			userSessionFactory* GetSessionFactory();

			// check connection info's valid.
			bool CheckConnectInfo(uint32 remoteId, const std::string& token) const;

		protected:
			// start pipe module.
			bool start(IPipeReporter* reporter);

			// initPipeDown initializes listening.
			bool initPipeDown(const std::vector<listenInfo> &listens);

			// initPipeUp initializes connecting.
			bool initPipeUp(const std::vector<connectInfo> &connects);

		private:
			// pipe config.
			CPipeConfig m_pipeConfig;

			// anet tcp event loop.
			anet::tcp::CEventLoop m_loop{ 1 };

			// anet tcp server.
			anet::tcp::CServer m_server;

			// anet tcp session factory.
			userSessionFactory m_sessionFactory;

			// anet tcp packet codec.
			anet::tcp::CBigCodec m_codec;

			// pipe report callback.
			IPipeReporter* m_pipeReporter{ nullptr };

			// time wheel module.
			STimeWheelSpace::CTimeWheel m_timeWheel;
		};
	}
}